package ebedynky.controllers;

import ebedynky.beans.*;
import ebedynky.editors.EditorFactory;
import ebedynky.services.*;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.validation.*;
import org.springframework.stereotype.Controller;
import org.springframework.ui.*;
import org.springframework.validation.*;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

/**
 * @author Ondrej David (davidon1)
 */
@Controller
public class OfferController {

    /**
     * Initialises the data binder.
     * @param binder the data binder to be initialised
     */
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        try {
            //        binder.setValidator(new OfferValidator());
            binder.registerCustomEditor(Supplier.class, EditorFactory.getSupplierIDEditor());
            binder.registerCustomEditor(DeliveryPlace.class, EditorFactory.getDeliveryPlaceIDEditor());
            binder.registerCustomEditor(Timestamp.class, EditorFactory.getTimestampFromStringEditor());
            binder.registerCustomEditor(Set.class, "suppliers", EditorFactory.getSupplierIDtoSetEditor());
        } catch (Exception ex) {
            Logger.getLogger(OfferController.class.getName()).log(Level.SEVERE, "Binder failed at OfferController", ex);
        }
    }

    /**
     * Fetches the index page when requested.
     * @param model data holder for this view
     * @return string representing page location
     */
    @RequestMapping(value = "/offer", method = RequestMethod.GET)
    public String getIndex(Model model) {
        return "offer/index";
    }

    /**
     * Fetches the offer adding page when requested.
     * @param model data holder for this view
     * @return string representing page location
     */
    @RequestMapping(value = "/offerAdd", method = RequestMethod.GET)
    public String getCreateForm(Model model) {
        model.addAttribute(new Offer());
        return "offer/createForm";
    }

    /**
     * Extracts the offer data from the form,
     * validates them and stores them into the db.
     * @param offer data from the form
     * @param result data binding result
     * @return string representing next (success/failure) page location
     */
    @RequestMapping(value = "/offerAdd", method = RequestMethod.POST)
    public String create(@Valid Offer offer, BindingResult result) {
        if (result.hasErrors()) {
            return "offer/createForm";
        }
        OfferService os = new OfferService();
        os.addOffer(offer);
        return "offer/index";
    }

    /**
     * Fetches the offer delete page when requested.
     * @param model data holder for this view
     * @return string representing page location
     */
    @RequestMapping(value = "/offerDel", method = RequestMethod.GET)
    public String getDeleteForm(Model model) {
        model.addAttribute(new Offer());
        return "offer/deleteForm";
    }

    /**
     * Deletes the corresponding offer data from the db.
     * @param offer data from the form
     * @param result data binding result
     * @return string representing next (success/failure) page location
     */
    @RequestMapping(value = "/offerDel", method = RequestMethod.POST)
    public String delete(@Valid Offer offer, BindingResult result) {
        if (result.hasErrors()) {
            return "offer/deleteForm";
        }
        OfferService os = new OfferService();
        os.deleteOffer(offer.getOfferID());
        return "offer/index";
    }

    /**
     * Fetches the offer select page when requested.
     * @param model data holder for this view
     * @return string representing page location
     */
    @RequestMapping(value = "/offerSel", method = RequestMethod.GET)
    public String getSelectForm(Model model) {
        model.addAttribute(new Offer());
        return "offer/selectForm";
    }

    /**
     * Selects the corresponding offer data from the db.
     * @param offer data from the form
     * @param result data binding result
     * @return string representing next (success/failure) page location
     */
    @RequestMapping(value = "/offerSel", method = RequestMethod.POST)
    public String select(@Valid Offer offer, BindingResult result) {
        if (result.hasErrors()) {
            return "offer/selectForm";
        }
        return "redirect:/offerMod/" + String.valueOf(offer.getOfferID());
    }

    /**
     * Fetches the offer modify page when requested.
     * @param id of the offer to modify
     * @param model data holder for this view
     * @return string representing page location
     */
    @RequestMapping(value = "/offerMod/{id}", method = RequestMethod.GET)
    public String getModifyForm(@PathVariable Integer id, Model model) {
        try {
            OfferService os = new OfferService();
            model.addAttribute(os.getOfferByID(id.intValue()));
        } catch (Exception ex) {
            Logger.getLogger(OfferController.class.getName()).log(Level.SEVERE, null, ex);
        }
        return "offer/modifyForm";
    }

    /**
     * Modifies the corresponding offer data in the db.
     * @param offer data from the form
     * @param result data binding result
     * @return string representing next (success/failure) page location
     */
    @RequestMapping(value = "/offerMod", method = RequestMethod.POST)
    public String modify(@Valid Offer offer, BindingResult result) {
        if (result.hasErrors()) {
            return "offer/modifyForm";
        }
        OfferService os = new OfferService();
        os.updateOffer(offer);
        return "offer/index";
    }

    /**
     * Adds a offer map extracted from the db as an attribute to the model.
     * @return Map<Integer, String> map of offerIDs and names
     */
    @ModelAttribute("offerList")
    protected Map<Integer, String> offerData() {
        Map<Integer, String> oMap = new ConcurrentHashMap<Integer, String>();
        OfferService os = new OfferService();
        List<Offer> list = os.getAllOffers();
        Iterator<Offer> it = list.iterator();
        Offer o;
        while (it.hasNext()) {
            o = it.next();
            oMap.put(o.getOfferID(), o.toString());
        }
        return oMap;
    }

    /**
     * Adds a deliveryplace list extracted from the db as an attribute to the model.
     * @return Map<Integer, String> list of DeliveryPlaces
     */
    @ModelAttribute("deliveryPlaceList")
    protected Map<Integer, String> deliveryplaceData() {
        Map<Integer, String> dpMap = new ConcurrentHashMap<Integer, String>();
        DeliveryPlaceService dps = new DeliveryPlaceService();
        List<DeliveryPlace> list = dps.getAllDeliveryPlaces();
        Iterator<DeliveryPlace> it = list.iterator();
        DeliveryPlace dp;
        while (it.hasNext()) {
            dp = it.next();
            dpMap.put(dp.getDeliveryPlaceID(), dp.toString());
        }
        return dpMap;
    }

    /**
     * Adds a supplier map extracted from the db as an attribute to the model.
     * @return Map<Integer, String> map of supplierIDs and names
     */
    @ModelAttribute("supplierList")
    protected Map<Integer, String> supplierData() {
        Map<Integer, String> sMap = new ConcurrentHashMap<Integer, String>();
        SupplierService ss = new SupplierService();
        List<Supplier> list = ss.getAllSuppliers();
        Iterator<Supplier> it = list.iterator();
        Supplier s;
        while (it.hasNext()) {
            s = it.next();
            sMap.put(s.getUserID(), s.toString());
        }
        return sMap;
    }
}